﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Microsoft.ResourceManagement.Samples.ResourceManagementClient;
using Microsoft.ResourceManagement.Samples.ResourceManagementClient.ResourceManagement;
using Microsoft.ResourceManagement.Samples.ResourceManagementClient.Utilities;

namespace SampleApplication
{
    /// <summary>
    /// This program shows sample usage of the resource management client.
    /// 
    /// This client is not intended for general consumption.
    /// Please consider it a form of documentation.
    /// The client may not work in all cases and all scenarios.
    /// It is only tested to work with the scenarios included in the blog topics below.
    /// Expect to make changes to the code for it to work for you.
    /// 
    /// Delete is known not to work for an undetermined reason.
    /// 
    /// These samples are described on the identity management blog:
    /// http://blogs.msdn.com/imex/
    /// </summary>
    class Program
    {
        // We set these variables so you may run these unit tests in your environment.
        // These are the default credentials for ILM "2" RC
        private const String User = "administrator";
        private const String Password = "Pass@word1";
        private const String Domain = "litware";
        // This is the id of a person object you wish to get in the get tests
        // This is the default guid for the administrator.
        private const String GetPersonId = "urn:uuid:b6ff5253-c85c-4bdf-be7c-a896094109d9";
        // This is the id of a group you wish to add a member in the put tests
        // This is the pre-populated group Litware Art Club
        private const String GetGroupId = "urn:uuid:fa4a8d6f-76b9-4c83-9e2e-70173070f471";

        // NOTE: Be sure to change app.config to use your server's name!
        // The default is localhost.

        private static System.Net.NetworkCredential GetCredentials()
        {
            return new NetworkCredential(User, Password, Domain);
        }

        static void Main(string[] args)
        {
            // If you are curious, originally this code existed in a visual studio test project.
            // However we migrated away from that to ensure this code would work with express editions
            // of Visual Studio

            //Topic11GetPerson();
            //Topic12GetPersonExtensions();
            Topic13EnumeratePerson();
            //Topic14EnumerateSchema();
            //Topic15CreateGroup();
            //Topic16AddMemberToGroup();

            Console.WriteLine("Press enter to continue...");
            Console.ReadLine();
        }

        static void Topic11GetPerson()
        {
            WSTransferClient transferClient = new WSTransferClient();
            transferClient.ClientCredentials = GetCredentials();
            String objectId = GetPersonId;
            ResourceManagementObject person = transferClient.Get(objectId);
            Assert.IsTrue(objectId.Equals(person.ObjectId));
            Console.WriteLine("Topic 11 Complete");
        }

        static void Topic12GetPersonExtensions()
        {
            WSTransferClient transferClient = new WSTransferClient();
            //transferClient.ClientCredentials = GetCredentials();
            String objectId = GetPersonId;
            String[] attribs = new String[]{
                "DisplayName",
                "FirstName",
                "LastName",
            };
            ResourceManagementObject person = transferClient.Get(objectId, attribs);
            Assert.IsTrue(objectId.Equals(person.ObjectId));
            Console.WriteLine("Topic 12 Complete");
        }

        static void Topic13EnumeratePerson()
        {
            WSEnumerationClient enumerationClient = new WSEnumerationClient();
            //enumerationClient.ClientCredentials = GetCredentials();

            List<string> selectionAttributes = null;
            List<string> sortingAttributes = null;

            selectionAttributes = new List<string> {
                "DisplayName"
                //,"Description"
                //,"Filter"
            };
            //sortingAttributes = new List<string> {
            //    "attributeID"
            //};

            //enumerationClient.Enumerate("/Person[AccountName = 'jzamora']");
            //enumerationClient.Enumerate("/oidNode[baseOID = 'e36bd00a-fd90-4759-a199-a745a6aae093']", selectionAttributes, sortingAttributes);
            //enumerationClient.Enumerate("/oidAllocation", selectionAttributes, sortingAttributes);
            //enumerationClient.Enumerate("/BindingDescription[BoundObjectType = /ObjectTypeDescription[DisplayName = 'Set']]/BoundAttributeType", selectionAttributes, sortingAttributes);
            enumerationClient.Enumerate(@"/Person[ObjectID != membersof(/Set[DisplayName = 'All Inactive People'])]", selectionAttributes, sortingAttributes);
            //enumerationClient.Enumerate(@"/Set[DisplayName = 'All Inactive People']", selectionAttributes, sortingAttributes);
            //enumerationClient.Enumerate(@"/Person[ObjectID != membersof('2cff24dc-d311-48db-ae6a-671dfd5ef7fa')]", selectionAttributes, sortingAttributes);
            List<ResourceManagementObject> objs = new List<ResourceManagementObject>();

            while (enumerationClient.IsContextValid)
            {
                foreach (ResourceManagementObject obj in enumerationClient.Pull())
                //foreach (ResourceManagementObject obj in enumerationClient.Pull(enumerationClient.NumItems-1, enumerationClient.NumItems))
                {
                    objs.Add(obj);
                }
            }

            foreach (ResourceManagementObject obj in objs)
            {
                foreach (string attribute in selectionAttributes)
                {
                    if (obj[attribute] != null)
                    {
                        Console.WriteLine("{0}: {1}", attribute, obj[attribute].AttributeSingleValue);
                    }
                }
                Console.WriteLine();
            }

        }

        static void Topic14EnumerateSchema()
        {
            WSEnumerationClient enumerationClient = new WSEnumerationClient();
            enumerationClient.ClientCredentials = GetCredentials();
            Dictionary<String, ResourceManagementObject> AttributeDescriptions = new Dictionary<string, ResourceManagementObject>();
            Dictionary<String, ResourceManagementObject> ObjectDescriptions = new Dictionary<string, ResourceManagementObject>();
            Dictionary<String, List<ResourceManagementObject>> Bindings = new Dictionary<string, List<ResourceManagementObject>>();

            // need to get these three ILM objects:
            // ObjectTypeDescription -- defines ILM objects
            // AttributeTypeDescription -- defines ILM attributes
            // BindingDescription -- maps attributes to objects

            enumerationClient.Enumerate("/AttributeTypeDescription");
            while (enumerationClient.IsContextValid)
            {
                foreach (ResourceManagementObject obj in enumerationClient.Pull())
                {
                    AttributeDescriptions[obj.ObjectId] = obj;
                }
            }
            enumerationClient.Enumerate("/ObjectTypeDescription");
            while (enumerationClient.IsContextValid)
            {
                foreach (ResourceManagementObject obj in enumerationClient.Pull())
                {
                    ObjectDescriptions[obj.ObjectId] = obj;
                }
            }
            enumerationClient.Enumerate("/BindingDescription");
            while (enumerationClient.IsContextValid)
            {
                foreach (ResourceManagementObject obj in enumerationClient.Pull())
                {
                    String boundObject = obj["BoundObjectType"].AttributeSingleValue.ToString();
                    if (Bindings.ContainsKey(boundObject) == false)
                    {
                        Bindings[boundObject] = new List<ResourceManagementObject>();
                    }
                    Bindings[boundObject].Add(obj);
                }
            }

            foreach (ResourceManagementObject objectDescription in ObjectDescriptions.Values)
            {
                Console.WriteLine(objectDescription["DisplayName"].AttributeSingleValue);
                foreach (ResourceManagementObject binding in Bindings[objectDescription.ObjectId])
                {
                    ResourceManagementObject attribute = AttributeDescriptions[binding["BoundAttributeType"].AttributeSingleValue.ToString()];
                    if (null == attribute)
                        continue;
                    Console.WriteLine("\t" + attribute["DisplayName"]);
                }
            }

            Console.WriteLine("Topic 14 Complete");
        }

        static void Topic15CreateGroup()
        {
            WSTransferClient transferClient = new WSTransferClient();
            transferClient.ClientCredentials = GetCredentials();

            ResourceManagementObject rmObject = new ResourceManagementObject("Group");
            rmObject["DisplayName"] = new ResourceManagementAttribute("DisplayName", "CreatedGroupDisplay");
            rmObject["Scope"] = new ResourceManagementAttribute("Scope", "Universal");
            rmObject["AccountName"] = new ResourceManagementAttribute("AccountName", "CreatedGroup");
            rmObject["Domain"] = new ResourceManagementAttribute("Domain", Domain);
            rmObject["MembershipAddWorkflow"] = new ResourceManagementAttribute("MembershipAddWorkflow", "None");
            rmObject["Owner"] = new ResourceManagementAttribute(true, "Owner");
            rmObject["Owner"].AddMultiValue(GetPersonId);
            rmObject["MembershipLocked"] = new ResourceManagementAttribute("MembershipLocked", "False");
            rmObject["Type"] = new ResourceManagementAttribute("Type", "Distribution");

            rmObject["MailNickname"] = new ResourceManagementAttribute("MailNickname", "CreatedGroupMailName");
            rmObject["DisplayedOwner"] = new ResourceManagementAttribute("DisplayedOwner", GetPersonId);

            String newGroupId = transferClient.Create(rmObject);
            Assert.IsNotNull(newGroupId);

            ResourceManagementObject retrievedGroup = transferClient.Get(newGroupId);
            Assert.IsNotNull(retrievedGroup);
            Assert.IsTrue(newGroupId.Equals(retrievedGroup.ObjectId));

            Console.WriteLine("Topic 15 Complete");
        }

        static void Topic16AddMemberToGroup()
        {
            ResourceManagementObject createdGroup = null;

            using (WSEnumerationClient enumerationClient = new WSEnumerationClient())
            {
                enumerationClient.ClientCredentials = GetCredentials();

                enumerationClient.Enumerate("/Group[DisplayName='CreatedGroupDisplay']");
                if (enumerationClient.IsContextValid)
                {
                    IList<ResourceManagementObject> groups = enumerationClient.Pull(1);
                    if (groups.Count > 0)
                    {
                         createdGroup = groups[0];
                    }
                }

                if (null == createdGroup)
                {
                    throw new InvalidOperationException("The created group was not found");
                }
            }

            if (createdGroup["ExplicitMember"] == null)
            {
                createdGroup["ExplicitMember"] = new ResourceManagementAttribute(true, "ExplicitMember");
            }
            createdGroup["ExplicitMember"] = ResourceManagementAttributeFactory.ConvertToMultiValuedAttribute(createdGroup["ExplicitMember"]);

            using (WSEnumerationClient enumerationClient = new WSEnumerationClient())
            {
                enumerationClient.ClientCredentials = GetCredentials();

                enumerationClient.Enumerate("/Person");
                while (enumerationClient.IsContextValid)
                {
                    foreach (ResourceManagementObject person in enumerationClient.Pull())
                    {
                        // Please note that ResourceManagementAttribute will note which are new and not.
                        createdGroup["ExplicitMember"].AddMultiValue(person.ObjectId);
                    }
                }
            }

            WSTransferClient transferClient = new WSTransferClient();
            transferClient.ClientCredentials = GetCredentials();

            transferClient.Put(createdGroup);

            Console.WriteLine("Topic 16 Complete");
        }
    }

    /// <summary>
    /// A simplified version of the one from Visual Studio's test suite.
    /// </summary>
    public sealed class Assert
    {

        internal static void IsTrue(bool testBool)
        {
            if (testBool == false)
                throw new Exception();
        }

        internal static void IsNotNull(Object testObject)
        {
            if (testObject == null)
                throw new Exception();
        }

        internal static void IsFalse(bool testBool)
        {
            IsTrue(!testBool);
        }
    }
}
